<!DOCTYPE html>
<html>
  <head>
    <meta http-equiv="content-type" content="text/html; charset=utf-8">
    <title>OpenTBS documentation - create OpenOffice and Ms Office documents
      with PHP</title>
    <script>
  // redirection if open without the menu at the TBS site
  if ( (document.location.href.indexOf('www.tinybutstrong.com') > 0)
        && (document.location.href.indexOf('tbs_plugin_opentbs.html') > 0)
	  ) {
  	document.location.href = "/opentbs.php?doc";
  }
</script> <style>
<!--
body, td, th {
	font-family: Arial, sans-serif;
	font-size: 13px;
}

/* makes first paragraph alignet to top in tables */
td > p:first-child ,
td > ul:first-child {
	margin-top: 0px;
} 

td th {
	vertical-align: top;
}

#main-body h4 {
	font-size: 13px;
	font-weight:normal;
	margin-bottom: 5px;
}
#main-body h5 {
	font-size: 13px;
	font-weight:normal;
	text-decoration:underline;
	margin-bottom: 5px;
}
#main-body ul {
	list-style-type: square;
	padding-left: 10px;
	line-height: 20px;
}
#main-body ul li ul {
	list-style-type: circle;
	padding-left: 14px;
	line-height: 20px;
}
.shift {
	margin-left: 10px;
	padding: 3px;
}
.code {
	font-family: "Courier New", Courier, monospace;
	font-size: 13px;
	color: #036;
	background-color: #E1EBFF;
	padding-top: 3px;
	padding-bottom: 3px;
}
.template {
	font-family: "Courier New", Courier, monospace;
	font-size: 12px;
	color: #030;
	background-color: #E1FFEB;
	margin-top: 3px;
	margin-bottom: 3px;
	padding-top: 3px;
	padding-bottom: 3px;
}
.versioning {
	font-style: italic;
	color: #060;
}
.category {
	color: #C33;
	font-weight: bold;
	font-size: 13px;
}
.smallcode {
	font-family: "Courier New", Courier, monospace;
	font-size: 13px;
	color: #036;
}
.small-list {
	list-style: circle;
}
.nowrap {
	white-space: nowrap;
}
.centered {
	text-align:center;
}
.top {
	vertical-align: top;
}
.warning {
	color: #F30;
}
.yes {
	color: #060;
}
.no {
	color: #C30;
}

-->
</style> <meta name="Keywords" content="openxml, odf, template">
  </head>
  <body>
    <!-- div main-body is used for insertion in the TBS menu -->
    <div id="main-body">
      <h1>OpenTBS - create OpenOffice and Ms Office documents with PHP</h1>
      <div>version 1.12.1, 2024-03-06 by Skrol29</div>
      <div>help file modified on 2024-03-06</div>
      <ol>
        <li><a href="#intro">Introduction</a></li>
        <li><a href="#install">Installing</a></li>
        <li><a href="#principles">Understanding principles</a></li>
        <li><a href="#coding">Synopsis and code examples</a>
          <ul>
            <li>4.1. <a href="#preparation">Preparation of TinyButStrong
                Template Engine with the OpenTBS plug-in</a></li>
            <li>4.2. <a href="#loadtemplate">Method LoadTemplate()</a></li>
            <li>4.3. <a href="#show">Method Show()</a></li>
            <li>4.4. <a href="#blockalias">Block Alias</a></li>
            <li>4.5. <a href="#chart">Charts - Change or read data of series in
                a chart</a></li>
            <li>4.6. <a href="#pic">Pictures - Change pictures in the document</a></li>
            <li>4.7. <a href="#col">Tables - Delete or merge columns in tables</a></li>
            <li>4.8. <a href="#mergecell">Tables - Merge cells vertically</a></li>
            <li>4.9. <a href="#cells">Workbook - Merging data in spreadsheet
                cells</a></li>
            <li>4.10. <a href="#ranges">Workbook - Read and writre ranges in a
                workbook</a></li>
            <li>4.11. <a href="#docfield">Merge document fields</a></li>
            <li>4.12. <a href="#other_commands">Other merging commands</a>
              <ul>
                <li><a href="#commands_for_all">For all types of documents</a></li>
                <li><a href="#commands_for_documents">For documents (ODT and
                    DOCX)</a></li>
                <li><a href="#commands_for_workbooks"> For workbooks (ODS and
                    XLSX)</a></li>
                <li> <a href="#commands_for_presentations">For presentations
                    (ODP and PPTX)</a><br>
                </li>
              </ul>
            </li>
            <li>4.13. <a href="#modify_files">Manage files in the archive</a></li>
            <li>4.14. <a href="#special_options">Special options</a></li>
          </ul>
        </li>
        <li><a href="#demo">Demo</a></li>
        <li><a href="#debug">Debugging your template</a></li>
        <li><a href="#zlib">What to do if Zlib extension is not enabled with
            PHP?</a></li>
        <li><a href="#license">License</a></li>
      </ol>
      <h2><a id="intro"></a>1. Introduction</h2>
      <p>OpenTBS is a plug-in for the <a href="http://www.tinybutstrong.com">TinyButStrong</a>
        Template Engine. </p>
      <p> TinyButStrong is a PHP Template Engine which has special template
        syntax and allows you to design templates in their natural editing
        tools. But it normally works only for Text files, including XML and
        HTML.</p>
      <p> With TinyButStrong and its plug-in OpenTBS, you can use the template
        engine to merge <strong>OpenOffice</strong> documents and <strong>Ms
          Office </strong> documents with lot of facilities. All <strong>OpenDocument
          Format</strong> (ODF) and <strong> Office Open XML</strong> (OOXML)
        can be merged with OpenTBS, and also XPS files (XPS is a PDF competitor
        provided by Microsoft). In fact, all zip archives containing
        Xml/Html/Text files can be merged with OpenTBS.</p>
      <p>Since version 1.10.0, OpenTBS can also read data in workbooks (<strong>xlsx</strong>
        and <strong>ods</strong> files).</p>
      <h5>What is special to OpenTBS:</h5>
      <ul>
        <li>Design your templates directly with OpenOffice or MS Office.</li>
        <li>No exe file needed to merge documents.</li>
        <li>No temporary files needed to merge documents.</li>
        <li>Output directly as an http download, a new file on the disk, or as a
          string (for file attachment for example).</li>
        <li>Works with PHP 8, PHP 7 and PHP 5.</li>
        <li>No PHP extension is required (If the Zlib extension is enabled it
          becomes easier to use templates, see more detail below)</li>
      </ul>
      <p> You should know Template Engines and more specifically <a href="http://www.tinybutstrong.com">TinyButStrong</a>
        to use OpenTBS.</p>
      <h2><a id="install"></a>2. Installing</h2>
      <h5>Requirements:</h5>
      <ul>
        <li>TinyButStrong version 3.12.0 or higher.</li>
        <li>PHP 8, PHP 7 or PHP 5.</li>
        <li>It is better to have the <a href="http://www.php.net/manual/en/book.zlib.php">Zlib</a>
          extension enabled on your PHP installation. If it's not, <a href="#zlib">here
            is what to do</a>.</li>
      </ul>
      <h5>Installation:</h5>
      <p> Just put the file "tbs_plugin_opentbs.php" with your PHP scripts.</p>
      <h2><a id="principles"></a>3. Understanding principles</h2>
      <p>It is important to figure out that documents made with LibreOffice,
        OpenOffice and Ms Office (since version 2007) are technically zip
        archives containing XML files, even if the extension of the document is
        not ".zip". Those zip archives can contain other file types like
        pictures or sounds, but the document structure and the text contents are
        saved as XML files. The <a href="./xml_synopsis.html">XML Synopsis</a>
        summarizes the key entities of XML sub-files contained in LibreOffice,
        OpenOffice and Ms Office documents.</p>
      <p>TinyButStrong can merge XML files, but cannot read zip archives by
        itself. The plug-in OpenTBS extends the TinyButStrong methods <a href="http://www.tinybutstrong.com/manual.php#php_loadtemplate">LoadTemplate()</a>
        and <a href="http://www.tinybutstrong.com/manual.php#php_show">Show()</a>
        to make them working with zip archives. <span id="result_box"><span title="">But
            you do not have to bother with it because OpenTBS is managing
            archives in a way that is quite invisible for you.</span></span></p>
      <p> When the OpenTBS plugin is installed, the LoadTemplate() method
        becomes able to first load a zip archive (a LibreOffice, OpenOffice or
        Ms Office document), and then to load the contents of any XML or Text
        files stored in the archive. Then you can load an merge the contents of
        XML or Text files with all features of the TinyButStrong template
        engine. TBS can merge fields and blocks only for the current loaded
        sub-file, but OpenTBS make you very easy to <a href="#modify_files">manage
          sub-files</a> and gives lot of facilities for special contents such as
        pictures, charts, ... . At the end, the Show() method does render the
        entire zip archive including modified stored files. The render can be
        done as an HTTP download, or a new file on the server's disk, or as a
        PHP string containg the binary of the result archive.</p>
      <p>Since OpenTBS version 1.3, you can also add and delete files in the
        archive.</p>
      <p><a id="extension"></a>OpenTBS has <strong>automatic extension
          recognition</strong>. When you load a document which has one of the
        following extensions { odt, odg, ods, odf, odp, odm, docx, xlsx, pptx },
        then the main XML file of the archive are automatically loaded, and some
        special character conversion are preset. For example, for all
        OpenDocument files, the stored file "content.xml" is automatically
        loaded.</p>
      <p> Since version 1.6.0, if the extension is not recognized then OpenTBS
        also try to find the document by the sub-file presence. And if all
        fails, then you can force the document type using a <a href="#force_doctype">special
          command</a>.</p>
      <h2><a id="coding"></a>4. Synopsis and code examples</h2>
      <h3><a id="preparation"></a>4.1. Preparation of TinyButStrong Template
        Engine with the OpenTBS plug-in</h3>
      <pre class="shift code">include_once('tbs_class.php');
include_once('tbs_plugin_opentbs.php');

$TBS = new clsTinyButStrong;
$TBS-&gt;Plugin(TBS_INSTALL, OPENTBS_PLUGIN);</pre>
      Or, with an autoloader :
      <pre class="shift code">$TBS = new clsTinyButStrong;
$TBS-&gt;Plugin(TBS_INSTALL, 'clsOpenTBS');</pre>
      <h3><a id="loadtemplate"></a>4.2. Method LoadTemplate()</h3>
      <h4>• Load an archive with the automatic extension recognition (<a href="#extension">explained
          above</a>): </h4>
      <div class="shift">
        <div class="code">$TBS-&gt;LoadTemplate('document.odt'); // Load the
          archive 'document.odt'. </div>
      </div>
      <div class="shift">
        <div class="code">$TBS-&gt;LoadTemplate('document.odt',
          OPENTBS_ALREADY_UTF8); // Load the archive and tells that the PHP
          script and merged data are already UTF8. </div>
      </div>
      <h4>• Load an archive without the automatic extension recognition:</h4>
      <div class="shift"><span class="versioning">(supported since OpenTBS
          version 1.1)</span>
        <div class="code">$TBS-&gt;LoadTemplate('document.odt#');</div>
      </div>
      <h4>• Load an archive with a PHP file handle:</h4>
      <div class="shift"><span class="versioning">(supported since OpenTBS
          version 1.8.1)</span>
        <pre class="code">$handle&nbsp;=&nbsp;tmpfile();
fwrite($handle,&nbsp;$binary_contents);
$TBS-&gt;LoadTemplate($handle);</pre>
      </div>
      <h4>• Load an archive and one file stored in this archive:</h4>
      <div class="shift code">$TBS-&gt;LoadTemplate('document.odt#content.xml');</div>
      <h4>• Load an archive and several files stored in this archive:</h4>
      <div class="shift code">$TBS-&gt;LoadTemplate('document.odt#content.xml;settings.xml');</div>
      <h4>• Unload the current template, so the template file is no longer
        locked:</h4>
      <div class="shift"><span class="versioning">(supported since OpenTBS
          version 1.9.5)</span>
        <div class="code">$TBS-&gt;LoadTemplate(false);</div>
      </div>
      <h4>• Load a stored file from the current archive:</h4>
      <div class="shift">
        <p>See command <a href="#opentbs_select_file">OPENTBS_SELECT_FILE</a>.</p>
      </div>
      <h4>• Load an archive with special data conversion:</h4>
      <div class="shift"><span class="versioning">(supported since OpenTBS
          version 1.3.2)</span>
        <div class="code">$TBS-&gt;LoadTemplate('document.odt',
          OPENTBS_ALREADY_UTF8);</div>
        <p>OpenTBS manages XML files that are UTF8 encoded. But by default, it
          assumes that all the data to merge (which can come from PHP or SQL) is
          Ascii encoded, and thus it performs conversions. If you want to define
          the data conversion, then you can use one of the following constants:</p>
        <ul>
          <li><span class="smallcode">OPENTBS_DEFAULT</span>: OpenTBS assumes
            that all data is ASCII encoded,</li>
          <li><span class="smallcode">OPENTBS_ALREADY_UTF8</span>: OpenTBS
            assumes that all data is already UTF8 encoded,</li>
          <li><span class="smallcode">OPENTBS_ALREADY_XML</span>: OpenTBS
            assumes that all data is already XML encoded, and thus it won't
            convert data at all. Take care of that option.</li>
        </ul>
        <p> Please note that if you need to change the data conversion for one
          or few fields only in your template, then you can use parameter "<span
            class="smallcode">htmlconv</span>" (see the TBS documentation for
          more details). </p>
      </div>
      <h3><a id="show"></a>4.3. Method Show()</h3>
      <p>Render options for OpenTBS:</p>
      <h4>• Render the merged archive as an HTTP download: ($file_name is
        optional)</h4>
      <div class="shift code">$TBS-&gt;Show(OPENTBS_DOWNLOAD, $file_name);</div>
      <h4>• Render the merged archive as an HTTP output with your customized
        HTTP headers:</h4>
      <div class="shift code">header(...); // your custom headers here<br>
        $TBS-&gt;Show(OPENTBS_DOWNLOAD + OPENTBS_NOHEADER); // output the binary
        file without header</div>
      <h4>• Render the merged archive as a new file saved on the server's disk:</h4>
      <div class="shift code">$TBS-&gt;Show(OPENTBS_FILE, $file_name);</div>
      <h4>• Render the merged archive as a PHP string:</h4>
      <div class="shift"> <span class="versioning">(supported since OpenTBS
          version 1.1)</span>
        <div class="code"> $TBS-&gt;Show(OPENTBS_STRING);<br>
          $string = $TBS-&gt;Source; </div>
        <p>When you use <span class="smallcode">OPENTBS_STRING</span> then
          there is no output for the client. But instead, the binary source of
          the archive is placed into property $TBS-&gt;Source. This feature can
          be useful, for example, when you want to place the merged document
          into an email as an attached file.</p>
      </div>
      <h3><a id="blockalias"></a>4.4. Block alias</h3>
      <p><span class="versioning">Block Alias are supported since OpenTBS
          version 1.8.0, they can work only with TBS 3.8.0 or higher</span>.</p>
      <p>The Block Alias are wrappers for defining TBS blocks on usual Libre
        Office and Ms Office entities. This helps to not referring directly to
        XML entities and to harmonize block definitions between types of
        documents. For example: you can use <span class="smallcode">block=tbs:row</span>
        instead of <span class="smallcode">block=table:table-row</span>.</p>
      <p> Some Block Alias, such as <span class="smallcode">tbs:page</span> and
        <span class="smallcode">tbs:section</span>, are also defining an entity
        that you cannot have with normal XML entities.</p>
      <h5>Block alias available according to the type of document :</h5>
      <table cellspacing="1" cellpadding="4" border="0">
        <tbody>
          <tr>
            <th rowspan="2" class="tbl-list" align="left">Alias</th>
            <th rowspan="2" align="left">Desciption</th>
            <th colspan="3" align="center">LibreOffice</th>
            <th colspan="3" align="center">Ms Office</th>
          </tr>
          <tr>
            <th class="centered">Writer<br>
              (odt)</th>
            <th class="centered">Calc<br>
              (ods)</th>
            <th class="centered">Impress<br>
              (odp)</th>
            <th class="centered">Word<br>
              (docx)</th>
            <th class="centered">Excel<br>
              (xlsx)</th>
            <th class="centered">PowerPoint<br>
              (pptx)</th>
          </tr>
          <tr>
            <td class="nowrap top smallcode">tbs:p</td>
            <td>A paragraph.</td>
            <td class="yes centered">yes</td>
            <td class="centered"><span class="no">no</span></td>
            <td class="centered"><span class="yes">yes</span></td>
            <td class="centered"><span class="yes">yes</span></td>
            <td class="centered"><span class="no">no</span></td>
            <td class="centered"><span class="yes">yes</span></td>
          </tr>
          <tr>
            <td class="nowrap top smallcode">tbs:title</td>
            <td>A title.</td>
            <td class="centered yes">yes</td>
            <td class="centered"><span class="no">no</span></td>
            <td class="centered"><span class="yes">yes</span></td>
            <td class="centered"><span class="yes">yes</span></td>
            <td class="centered"><span class="no">no</span></td>
            <td class="centered"><span class="yes">yes</span></td>
          </tr>
          <tr>
            <td class="top smallcode nowrap">tbs:section</td>
            <td>A section of text.</td>
            <td class="centered yes">yes</td>
            <td class="centered"><span class="no">no</span></td>
            <td class="centered"><span class="no">no</span></td>
            <td class="centered"><span class="yes">yes (*)</span></td>
            <td class="centered"><span class="no">no</span></td>
            <td class="centered"><span class="no">no</span></td>
          </tr>
          <tr>
            <td class="top smallcode nowrap">tbs:table</td>
            <td>A table inserted in the document.</td>
            <td class="centered"><span class="yes">yes</span></td>
            <td class="centered"><em>a sheet</em></td>
            <td class="centered"><span class="yes">yes</span></td>
            <td class="centered"><span class="yes">yes</span></td>
            <td class="centered"><span class="no">no</span></td>
            <td class="centered"><span class="yes">yes</span></td>
          </tr>
          <tr>
            <td class="top smallcode nowrap">tbs:row</td>
            <td>A row of a table.</td>
            <td class="centered"><span class="yes">yes</span></td>
            <td class="centered"><span class="yes">yes</span></td>
            <td class="centered"><span class="yes">yes</span></td>
            <td class="centered"><span class="yes">yes</span></td>
            <td class="centered"><span class="yes">yes</span></td>
            <td class="centered"><span class="yes">yes</span></td>
          </tr>
          <tr>
            <td class="top smallcode nowrap">tbs:cell</td>
            <td>A cell of a table.</td>
            <td class="centered"><span class="yes">yes</span></td>
            <td class="centered"><span class="yes">yes</span></td>
            <td class="centered"><span class="yes">yes</span></td>
            <td class="centered"><span class="no">no</span></td>
            <td class="centered"><span class="yes">yes</span></td>
            <td class="centered"><span class="yes">yes</span></td>
          </tr>
          <tr>
            <td class="top smallcode nowrap">tbs:comment</td>
            <td>A comment.</td>
            <td class="centered"><span class="yes">yes</span></td>
            <td class="centered"><span class="yes">yes</span></td>
            <td class="centered"><span class="yes">yes</span></td>
            <td class="centered"><span class="no">no</span></td>
            <td class="centered"><span class="no">no</span></td>
            <td class="centered"><span class="no">no</span></td>
          </tr>
          <tr>
            <td class="top smallcode nowrap">tbs:page</td>
            <td>A page defined by an explicit page break before a paragraph.(*)</td>
            <td class="centered"><span class="yes">yes</span></td>
            <td class="centered"><span class="no">no</span></td>
            <td class="centered"><span class="no">no</span></td>
            <td class="centered"><span class="yes">yes (*)</span></td>
            <td class="centered"><span class="no">no</span></td>
            <td class="centered"><span class="no">no</span></td>
          </tr>
          <tr>
            <td class="top smallcode nowrap">tbs:slide</td>
            <td>A slide.</td>
            <td class="centered"><span class="no">no</span></td>
            <td class="centered"><span class="no">no</span></td>
            <td class="centered"><span class="yes">yes</span></td>
            <td class="centered"><span class="no">no</span></td>
            <td class="centered"><span class="no">no</span></td>
            <td class="centered"><span class="no">no</span></td>
          </tr>
          <tr>
            <td class="top smallcode nowrap">tbs:sheet</td>
            <td>A worksheet.</td>
            <td class="centered"><em>a table</em></td>
            <td class="centered yes">yes</td>
            <td class="centered"><span class="no">no</span></td>
            <td class="centered"><span class="no">no</span></td>
            <td class="centered"><span class="no">no</span></td>
            <td class="centered"><span class="no">no</span></td>
          </tr>
          <tr>
            <td class="top smallcode nowrap">tbs:draw</td>
            <td>A single draw, or set of draws (Ms Word)</td>
            <td class="centered"><span class="yes">yes</span></td>
            <td class="centered"><span class="yes">yes</span></td>
            <td class="centered"><span class="yes">yes</span></td>
            <td class="centered"><span class="yes">yes</span></td>
            <td class="centered"><span class="yes">yes</span></td>
            <td class="centered"><span class="yes">yes</span></td>
          </tr>
          <tr>
            <td class="top smallcode nowrap">tbs:drawgroup</td>
            <td>A group of draws.</td>
            <td class="centered"><span class="yes">yes</span></td>
            <td class="centered"><span class="yes">yes</span></td>
            <td class="centered"><span class="yes">yes</span></td>
            <td class="centered"><span class="yes">yes</span></td>
            <td class="centered"><span class="yes">yes</span></td>
            <td class="centered"><span class="yes">yes</span></td>
          </tr>
          <tr>
            <td class="top smallcode nowrap">tbs:drawitem</td>
            <td>A single draw item among a set of items.</td>
            <td class="centered"><span class="yes">yes</span></td>
            <td class="centered"><span class="yes">yes</span></td>
            <td class="centered"><span class="yes">yes</span></td>
            <td class="centered"><span class="yes">yes</span></td>
            <td class="centered"><span class="yes">yes</span></td>
            <td class="centered"><span class="yes">yes</span></td>
          </tr>
          <tr>
            <td class="top smallcode nowrap">tbs:listitem</td>
            <td>An item of a bullet list.</td>
            <td class="centered"><span class="yes">yes</span></td>
            <td class="centered"><span class="no">no</span></td>
            <td class="centered"><span class="yes">yes</span></td>
            <td class="centered"><span class="yes">yes</span></td>
            <td class="centered"><span class="no">no</span></td>
            <td class="centered"><span class="yes">yes</span></td>
          </tr>
        </tbody>
      </table>
      <h5>Notes (*)</h5>
      <ul>
        <li><span class="code">tbs:page</span> in a DOCX: works with the two
          ways for defining a page break: (1) insert a section break doing a
          page break, or (2) use the paragraph property named <em>page break
            before</em>.</li>
        <li><span class="code">tbs:page</span> in a DOCX: the TBS tag using the
          alias <span class="smallcode">tbs:page</span> must not be placed in
          the last paragraph of the page if it uses a section break doing a page
          break. This is a knowed bug. Instead, use the paragraph property named
          <em>page break before</em>, or move the TBS tag in another paragraph.</li>
        <li><span class="smallcode">tbs:section</span> in a DOCX: this alias
          points out avery kind of sections, including thoses defined with a
          section break doing a page break</li>
      </ul>
      <h3><a id="chart"></a>4.5. Change or read data of series in a chart</h3>
      <h4>• <a id="opentbs_chart"></a>Change series in a chart:</h4>
      <div class="shift"> <span class="versioning">(supported since OpenTBS
          version 1.6.0, for Ms Word and Ms Powerpoint, since version 1.8.0 for
          LibreOffice)</span>
        <div class="code">Example: $TBS-&gt;PlugIn(OPENTBS_CHART, $ChartRef,
          $SeriesNameOrNum, $NewValues, $NewLegend=false)</div>
        <p>This command changes the values of a series in a Chart of the
          document. The chart will be automatically actualized when the merged
          document is opened because OpenTBS also breaks the link between the
          chart and its cached view. It can also delete or rename the series in
          the chart.</p>
        <p> The result is <span class="smallcode">true</span> if the series is
          modified with success, otherwise the result is <span class="smallcode">false</span>.
        </p>
        <table width="100%" cellspacing="1" cellpadding="4" border="0">
          <tbody>
            <tr>
              <th class="top" align="left">Argument</th>
              <th align="left">Description</th>
            </tr>
            <tr>
              <td class="top smallcode">
                <p>$ChartRef</p>
              </td>
              <td class="top">
                <p>The reference to find the chart. This value can be either:</p>
                <ul>
                  <li>The name of a field placed anywhere in the Alternative
                    Text property of the frame that embeds the chart. <span class="versioning">(supported
                      since OpenTBS 1.10.4)</span>. <br>
                    This name must be unique for charts in the entire document.
                    <br>
                    For example: <code>$ChartRef = 'my_chart'</code> is
                    corresponding to the field <code>[my_chart]</code> placed
                    in the Alt Text property. <br>
                    The property Alt Text of the frame that embeds the chart is
                    available in both Ms Office and LibreOffice. <br>
                    In Ms Office you can retrieve this property from the
                    contextual menu of the frame, and choose <em>Alt. Text...<em>.
                        <br>
                        In LibreOffice you can retrieve this property from the
                        contextual menu of the frame, and choose <em>Description...<em>,
                            or sometimes <em>Properties...<em> in Writer. </em></em></em></em></em></em></li>
                  <em><em><em>
                        <li>The order number of the chart in the document (first
                          is number 1).</li>
                        <li>Deprecated: <code>$ChartRef</code> can aslo be
                          exactly the property title of frame that embeds the
                          chart <span class="versioning">(supported since
                            OpenTBS 1.8.0)</span>. <br>
                          Note: In Ms Office, this property is no more available
                          since Ms Office 2019. <br>
                          Note: In LibreOffice this property can sometimes be
                          captioned "Alternative - text only" in Writer. </li>
                      </em></em></em>
                </ul>
                <em><em><em>
                      <p> You can use the command <a href="#debugmode">OPENTBS_DEBUG_INFO</a>
                        in order to view all charts in the document that OpenTBS
                        can manage.<br>
                        You can use the command <a href="#opentbs_chart_info">OPENTBS_CHART_INFO</a>
                        in order to read data in the chart. </p>
                      <p>Deprecated since version 1.8.0: in previous version, <span
                          class="smallcode">$ChartRef</span> could be the
                        internal name of the XML file that contains the chart
                        definition, with or without the extension. Such as <span
                          class="smallcode">'chart1'</span>.</p>
                    </em></em></em></td>
            </tr>
            <tr>
              <td class="top smallcode">
                <p>$SeriesNumOrName</p>
              </td>
              <td class="top">
                <p>Exact caption of the series in the chart, or its number
                  (first is number 1). Typically <span class="smallcode">'Series
                    1'</span> or <span class="smallcode">1</span>. </p>
              </td>
            </tr>
            <tr>
              <td class="top smallcode">
                <p>$NewValues</p>
              </td>
              <td class="top">
                <p>The new data of the series. Must be an array, or value <span
                    class="smallcode">false</span> if you want to delete the
                  series.</p>
                <p> The array can store data with 3 possibilities:</p>
                <p> Structure #1: <span class="code">$NewValues = array(
                    array('cat1', 'cat2', 'cat3', ...), array(val1, val2, val3,
                    ...) );</span></p>
                <p> Structure #2: <span class="code">$NewValues =
                    array('cat1'=&gt;val1, 'cat2'=&gt;val2, 'cat3'=&gt;val3,
                    ...);</span></p>
                <p> Structure #3: <span class="code">$NewValues = array(
                    array(x1, y1), array(x2,y2), array(x3, y3), ...);</span> </p>
                <p>Notes :</p>
                <ul>
                  <li>A chart may have some values missing for one series and
                    not for others. You can define a missing value for a
                    category using PHP values <span class="smallcode">null</span>,
                    <span class="smallcode">'NULL'</span>, <span class="smallcode">false</span>
                    or <span class="smallcode">''</span> (empty string).</li>
                  <li>Structure #3 is supported only for LibreOffice, and is
                    required when the chart type is <strong>XY (Scatter)</strong>,
                    <strong>Bubble</strong> or<strong> Stock</strong>. Use 2
                    values in each items for XY, 3 for Bubble, and 4 for Stock.</li>
                  <li>Structure #1 is required for Ms Office when the chart type
                    is <strong>XY (Scatter)</strong>. Bubble and Stock are not
                    yet supported for Ms Office.</li>
                </ul>
              </td>
            </tr>
            <tr>
              <td class="top smallcode">
                <p>$NewLegend</p>
              </td>
              <td class="top">
                <p>Optional. The new caption of the series. </p>
              </td>
            </tr>
          </tbody>
        </table>
        <h5>Please note:</h5>
        <ul>
          <li>The type of the chart cannot be changed.</li>
          <li>Some charts may not be recognized by this feature when the Word
            document is created with Word &lt;= 2007 or is saved with a
            Compatibility Mode. You have to convert charts to have it work
            (right on the chart and choose "Convert"). You can use the command <a
              href="#debugmode">OPENTBS_DEBUG_INFO</a> in order to view all
            unsupported charts in the document.</li>
          <li>With Ms Office, the chart must not be linked to external data
            (such as an Excel worksheet). Otherwise the chart will be
            automatically actualized back the previous values when it will be
            opened. </li>
        </ul>
        <p class="versioning">Charts in worksheets (DOCX and ODS files) are
          supported since OpenTBS version 1.9.12.</p>
        <p class="versioning">Before version OpenTBS 1.9.12, the visual Data
          Editor in Ms Office softwares (Excel, Word, Powerpoint) becomes
          unavailable on a merged chart.</p>
      </div>
      <h4> <a id="opentbs_chart_info2"></a>Delete a category in a chart:</h4>
      <div class="shift"> <span class="versioning">(supported since OpenTBS
          version 1.9.11)</span>
        <div class="code">Example: $ok =
          $TBS-&gt;PlugIn(OPENTBS_CHART_DELETE_CATEGORY, $ChartRef, $Categories,
          $NoErr = false)</div>
        <p>This command delete one or several categories in the chart. It
          returns <span class="smallcode">true</span> if succeed.</p>
        <p>Argument <span class="smallcode">$Categories</span> can be either
          the name of a single category, an array of names, or the keyword <span
            class="smallcode">'*'</span> wich mean all categories.</p>
        <p>By default an error occurs if one of the searched categories is not
          found in the chart. But if your set argument <span class="smallcode">$NoErr</span>
          to <span class="smallcode">true</span> then the function returns <span
            class="smallcode">false</span> and no error occurs.</p>
        <p><span class="versioning">Array of names and the keyword '*' are
            supported since OpenTBS version 1.9.12.</span></p>
      </div>
      <h4>• <a id="opentbs_chart_info"></a>Read series in a chart:</h4>
      <div class="shift"> <span class="versioning">(supported since OpenTBS
          version 1.9.5)</span>
        <div class="code">Example: $info = $TBS-&gt;PlugIn(OPENTBS_CHART_INFO,
          $ChartRef, $Complete=false)</div>
        <p>This command returns information about all series in the chart.</p>
        <p> The result is an associative array whose structure depends on
          argument <span class="smallcode">$Complete</span>. </p>
        <table width="100%" cellspacing="1" cellpadding="4" border="0">
          <tbody>
            <tr>
              <th class="top" align="left">Argument</th>
              <th align="left">Description</th>
            </tr>
            <tr>
              <td class="top smallcode">
                <p>$ChartRef</p>
              </td>
              <td class="top">
                <p>The reference to find the chart. Same as <a href="#opentbs_chart">OPENTBS_CHART</a>.</p>
              </td>
            </tr>
            <tr>
              <td class="top smallcode">
                <p>$Complete</p>
              </td>
              <td class="top">
                <p>If<span class="smallcode"> $Complete</span> = <span class="smallcode">false</span>,
                  the command returns a simple list of all series and theirs
                  corresponding data with structue #1 described in <span class="smallcode"><a
                      href="#chart">OPENTBS_CHART</a></span>.</p>
                <pre class="code">// Example :
array (
  'Series 1' =&gt; array(
      0 =&gt; array (0 =&gt; 'Category A', 1 =&gt; 'Category B', 2 =&gt; 'Category C'),
      1 =&gt; array (0 =&gt; '2', 1 =&gt; '2.1', 2 =&gt; false,),
  ),
  'Series 2' =&gt; array(
      0 =&gt; array (0 =&gt; 'Category A', 1 =&gt; 'Category B', 2 =&gt; 'Category C',),
      1 =&gt; array (0 =&gt; '7', 1 =&gt; '7.1', 2 =&gt; '6.9',),
  ),
  ...
); </pre>
                <p>If<span class="smallcode"> $Complete</span> = <span class="smallcode">true</span>,
                  the command return an array with information about subfiles,
                  and also all the series (name, categories, values) in a
                  different structure.</p>
                <pre class="code">// Example :
array (
  'file_idx' =&gt; 17,
  'file_name' =&gt; 'Object 1/content.xml',
  'parent_idx' =&gt; 19,
  'parent_name' =&gt; 'content.xml',
  'series' =&gt; array (
    0 =&gt; array (
      'name' =&gt; 'Series 1',
      'cat' =&gt; array (0 =&gt; 'Category A', 1 =&gt; 'Category B', 2 =&gt; 'Category C',),
      'val' =&gt; array (0 =&gt; '2', 1 =&gt; '2.1', 2 =&gt; false,),
    ),
    1 =&gt; array (
      'name' =&gt; 'Series 2',
      'cat' =&gt; array (0 =&gt; 'Category A', 1 =&gt; 'Category B', 2 =&gt; 'Category C',),
      'val' =&gt; array (0 =&gt; '7', 1 =&gt; '7.1', 2 =&gt;'6.9',),
    ),
  ...
); </pre>
              </td>
            </tr>
          </tbody>
        </table>
      </div>
      <h3><a id="pic"></a>4.6. Change pictures in the document</h3>
      <h4>• Change an internal picture with a new one:</h4>
      <div class="shift"> <span class="versioning">(supported since OpenTBS
          version 1.4.0, for OpenOffice and MsOffice documents only)</span>
        <div class="template">Example: [onshow.x;ope=changepic]</div>
        <p>In the example above, $x is a PHP global variable containing the name
          of an external picture file (relative or absolute path). Of course you
          can use this feature on TBS fields merged with <a href="http://www.tinybutstrong.com/manual.php#php_mergeblock">MergeBlock()</a>.</p>
        <p> When a TBS field having <span class="smallcode">"ope=changepic"</span>
          is merged in the template, then OpenTBS will search the first picture
          located before the field (see parameter <span class="smallcode">tagpos</span>
          below for another position), and then it will change the picture
          assuming that the value of the field is the path for a picture file on
          the server. You don't have to care about loading the picture file in
          the document, OpenTBS will manage this for you.</p>
        <p>Note that parameter <span class="smallcode">"ope=changepic"</span>
          is a feature provided by the OpenTBS plug-in, which extends the "<a href="http://www.tinybutstrong.com/manual.php#html_field_prm_ope">ope</a>"
          parameter natively present with TBS.</p>
        <p>Instead of change a picture with a TBS tag, you can also do it
          manually at the PHP side using the command <a href="#other_commands">OPENTBS_CHANGE_PICTURE</a>.</p>
        <p>Known limitations:</p>
        <ul>
          <li>SVG pictures are not supported for Ms Office templates. Nor as an
            image to replace in the template, nor as an image to insert.</li>
          <li>Note that since OpenTBS version 1.8.0, you can change picture in
            Ms Excel worksheet. You must put the TBS field inside the picture
            description and use parameter "tagpos=inside". Before this version
            it was not possible to change pictures in an Ms Excel worksheet.</li>
        </ul>
        <p>Options:</p>
        <p>In order to simplify your coding, they are other complementary
          optional parameters: </p>
        <table style="margin-left:20px;" cellspacing="1" cellpadding="4" border="0">
          <tbody>
            <tr>
              <th align="left">Parameter</th>
              <th align="left">Description</th>
            </tr>
            <tr>
              <td class="top"><span class="smallcode">tagpos</span></td>
              <td>
                <p>Supported values are "<span class="smallcode">after</span>",
                  "<span class="smallcode">before</span>" and "<span class="smallcode">inside</span>".
                  This option indicates the position of the TBS tag relativelly
                  to the target picture.</p>
                <p> The default value is "<span class="smallcode">after</span>",
                  it means that the TBS tag (the one with "<span class="smallcode">ope=changepic</span>")
                  must be placed after the picture.</p>
                <p> You can use "<span class="smallcode">tagpos=inside</span>"
                  when you put the TBS field in the Description or Title of the
                  image (LibreOffice/OpenOffice or Ms Office). </p>
                <ul>
                  <li>This option won't work if you put the TBS tag inside the
                    property Name of an image in LibreOffice/OpenOffice.</li>
                  <li> In Ms Word 2007, property Description and Title are
                    supported but not available for editing, but you can use
                    "Alternative text" (in the "Web" tab of the Size dialog box)
                    , ot the URL, or the Toolipt of a Link on the image.</li>
                  <li> In Ms Excel, you must use "tagpos=inside" because
                    pictures are not saved in the sheet, they are not positioned
                    relativelly to cells.</li>
                </ul>
                <p> <span class="versioning">Parameter tagpos is supported
                    since OpenTBS version 1.8.0. Previsouly the TBS tag had to
                    be placed after the picture.</span></p>
              </td>
            </tr>
            <tr>
              <td class="top"><span class="smallcode">adjust</span></td>
              <td>
                <p>Adjust the size of the picture in the document. This
                  parameter requires that PHP is configured with the <a href="http://www.php.net/manual/en/book.image.php">GD</a>
                  extension, which is usually the case.</p>
                <p> Values can be on of the followings: </p>
                <table cellspacing="0" cellpadding="3" border="0">
                  <tbody>
                    <tr>
                      <td class="top"><span class="smallcode">adjust</span> (or
                        <span class="smallcode">adjust=inside</span>)</td>
                      <td>The picture is adjusted to enter into the picture
                        bounds of the template.</td>
                    </tr>
                    <tr>
                      <td class="top"><span class="smallcode">adjust=samewidth</span></td>
                      <td>The picture is adjusted to have the same width than
                        the picture of the template.</td>
                    </tr>
                    <tr>
                      <td class="top smallcode">adjust=sameheigth</td>
                      <td>The picture is adjusted to have the same height than
                        the picture of the template.</td>
                    </tr>
                    <tr>
                      <td class="top"><span class="smallcode">adjust=100%</span>
                        (or another pourcentage) </td>
                      <td>The picture is adjusted to be proportional to the
                        originial size.</td>
                    </tr>
                  </tbody>
                </table>
                <p class="versioning">Parameter adjust is supported since
                  OpenTBS version 1.7.0.</p>
              </td>
            </tr>
            <tr>
              <td class="top"><span class="smallcode">unique</span></td>
              <td>
                <p>Indicate to OpenTBS that the original picture is unique in
                  the template and can be deleted. This actually saves size of
                  the final document.<br>
                  The value of argument <span class="smallcode">unique</span>
                  can be omitted. If the value is 1 or ommited, then the
                  original picture is deleted from the template.</p>
                <p>If the original picture is in fact displayed somewhere else
                  in the template, that may produce a missing picture.</p>
                <p> <span class="versioning">Parameter unique is supported
                    since OpenTBS version 1.9.1.</span></p>
              </td>
            </tr>
            <tr>
              <td class="top"><span class="smallcode">from</span></td>
              <td>
                <p>This option reformulates the path of the new picture to
                  insert. The parameter's value can contain the [val] keyword or
                  any [var] fields, they work the same way as with parameter "<a
                    href="http://www.tinybutstrong.com/manual.php#html_field_prm_file"
                    class="smallcode">file</a>". </p>
                <div class="template">Example:
                  [onshow.x;ope=changepic;from='../pic/[val].gif']</div>
              </td>
            </tr>
            <tr>
              <td class="top"><span class="smallcode">as</span></td>
              <td>
                <p>This option reformulates the name of the picture that it will
                  take inside the document. It is rare to need it, but it can
                  help in some cases. Note that the external picture file is not
                  renamed. The new name must be defined without path. The
                  parameter's value can contain the [val] keyword or any [var]
                  fields, they work the same way as with parameter "<a href="http://www.tinybutstrong.com/manual.php#html_field_prm_file"
                    class="smallcode">file</a>". </p>
                <div class="template">Example:
                  [onshow.x;ope=changepic;as='[val].gif']</div>
              </td>
            </tr>
            <tr>
              <td class="top"><span class="smallcode">default</span></td>
              <td>
                <p>This option defines the picture that should be used when the
                  expected one is not found. The parameter's value must be the
                  path of a file on the server, or the keyword "<span class="smallcode">current"</span>.<br>
                  If the value is <span class="smallcode">"current"</span> then
                  OpenTBS will let the current picture of the template if the
                  new picture is not found.</p>
                <p> <span class="versioning">Since OpenTBS version 1.8.0 the
                    default value is "current". In prior versions, there was no
                    default value and an OpenTBS error message was prompted if
                    the new image was not found. </span></p>
              </td>
            </tr>
          </tbody>
        </table>
      </div>
      <h3><a id="col"></a>4.7. Delete or merge columns in a table</h3>
      <h5><a id="delcol"></a>4.7.1 Delete columns in a table</h5>
      <p>Parameter "<span class="smallcode">ope=delcol</span>" enables you to
        delete specified columns in a table in an Ms Word document (docx) or any
        LibreOffice document.</p>
      <p> Limitations of parameter "<span class="smallcode">ope=delcol</span>" :</p>
      <ul>
        <li>It will produce a wrong result if there is any cell with a merged
          style before of within the columns to delete using OpenTBS.</li>
        <li>If used with other <span class="smallcode">"ope"</span> options,
          then it must be the last one. This is because it avoid the usual
          merging process. Example : <span class="smallcode">ope=docfield,delcol</span>.</li>
      </ul>
      <p> You have to put a TBS field anywhere inside the table with the
        following parameters:</p>
      <table cellspacing="1" cellpadding="4" border="0">
        <tbody>
          <tr>
            <td class="top"><span class="template">ope=delcol</span></td>
            <td>activate the deletion feature</td>
          </tr>
          <tr>
            <td class="top"><span class="template">colnum=...</span></td>
            <td>
              <p>(ignored if <span class="template">colset</span> is defined)
                define the column numbers to delete. By default, this parameter
                is the merged value.<br>
                It can be :</p>
              <ul class="small-list">
                <li> a number (first column is number 1)</li>
                <li> a range (tow columns numbers separated with '-')</li>
                <li>a list of numbers or ranges separated with coma (,)</li>
              </ul>
              <p>Both parameters "<span class="template">colnum</span>" and "<span
                  class="template">colshift</span>" can contain [val] and [var]
                fields. Unfortunaltely parameter <span class="template">"ope"</span>
                is processed before parametre <span class="template">"if"</span>,
                so the merged value must be directly the colums to delete.</p>
            </td>
          </tr>
          <tr>
            <td class="top"><span class="template">colshift=...</span></td>
            <td>(optional, ignored if <span class="template">colset</span> is
              defined) if parameter <span class="template">colnum</span> has
              only one value then parameter <span class="template">colshift</span>
              extends the number of columns to delete to the left (if positive)
              or to the right (if negative).</td>
          </tr>
          <tr>
            <td class="top"><span class="template">colset=...</span></td>
            <td>
              <p>Define several set of columns, seperated with pipe (|). When
                this parameters is used, then OpenTBS wil delete the set of
                columns corresponding to the merged value.</p>
            </td>
          </tr>
        </tbody>
      </table>
      <p>If a column number to delete is empty (''), or zero (0), or negative,
        or over the actual number of colmun int the table, then the value is
        ignored whitout raising error.</p>
      <div class="shift">
        <p>Examples:</p>
        <table cellspacing="1" cellpadding="4" border="0">
          <tbody>
            <tr>
              <th align="left">Example</th>
              <th align="left">Description</th>
            </tr>
            <tr>
              <td class="top">
                <p><span class="template">[onshow.col_to_delete;ope=delcol]</span></p>
              </td>
              <td>
                <p>if <span class="smallcode">$col_to_delete = 3</span>, then
                  it will delete columns 3.<br>
                  if <span class="smallcode">$col_to_delete = array(5,8)</span>,
                  then it will delete columns 5,8. <br>
                  if <span class="smallcode">$col_to_delete = '5,8'</span>,
                  then it will delete columns 5,8. <br>
                  if <span class="smallcode">$col_to_delete = '5-8'</span>,
                  then it will delete columns 5,6,7,8.<br>
                  if <span class="smallcode">$col_to_delete = '1,3,5-8'</span>,
                  then it will delete columns 1,3,5,6,7,8. <br>
                  if <span class="smallcode">$col_to_delete = 0</span>, then it
                  will delete no columns.<br>
                  if <span class="smallcode">$col_to_delete = ''</span>, then
                  it will delete no columns. </p>
              </td>
            </tr>
            <tr>
              <td class="top">
                <p><span class="template">[onshow.col_to_delete;ope=delcol;colshift=2]</span></p>
              </td>
              <td>
                <p>if <span class="smallcode">$col_to_delete = 3</span>, then
                  it will delete columns 3, 4, 5.<br>
                  if <span class="smallcode">$col_to_delete = 0</span>, then it
                  will delete no columns. </p>
              </td>
            </tr>
            <tr>
              <td class="top">
                <p><span class="template">[onshow.set_to_delete;ope=delcol;colset=3]</span></p>
              </td>
              <td>
                <p>if <span class="smallcode">$set_to_delete = 1</span>, then
                  it will delete columns 3 (that is set #1).</p>
              </td>
            </tr>
            <tr>
              <td class="top">
                <p><span class="template">[onshow.set_to_delete;ope=delcol;colset=3-5]</span></p>
              </td>
              <td>
                <p>if <span class="smallcode">$set_to_delete = 1</span>, then
                  it will delete columns 3 to 5 (that is set #1).</p>
              </td>
            </tr>
            <tr>
              <td class="top">
                <p><span class="template">[onshow.set_to_delete;ope=delcol;colset=3,5]</span></p>
              </td>
              <td>
                <p>if <span class="smallcode">$set_to_delete = 1</span>, then
                  it will delete columns 3 and 5 (that is set #1).</p>
              </td>
            </tr>
            <tr>
              <td class="top">
                <p><span class="template">[onshow.set_to_delete;ope=delcol;colset=1,7-10|4,5,6]</span></p>
              </td>
              <td>
                <p>if <span class="smallcode">$set_to_delete = 1</span>, then
                  it will delete columns 1,7,8,9,10 (that is set #1).<br>
                  if <span class="smallcode">$set_to_delete = 2</span>, then it
                  will delete columns 4,5,6 (that is set #2).<br>
                  if <span class="smallcode">$set_to_delete = 0</span>, then it
                  will delete no columns.<br>
                  if <span class="smallcode">$set_to_delete = array(1,2)</span>,
                  then it will delete columns of set #1 and #2. </p>
              </td>
            </tr>
          </tbody>
        </table>
      </div>
      <p class="versioning">Parameter "ope=delcol" is supported since OpenTBS
        version 1.8.0.<br>
        Parameter "colset" is supported since OpenTBS version 1.10.0.<br>
        Parameter "colnum" is optional since OpenTBS version 1.10.0.</p>
      <h5><a id="parallell"></a>4.7.2 Merge dynamic columns in a table</h5>
      <p>Parameter "<span class="smallcode">parallel=tbs:table</span>" enables
        you to create dynamic columns in a table of an Ms Word Document or any
        LibreOffice document.</p>
      <p> Limitations: </p>
      <ul>
        <li>Parameter "<span class="smallcode">parallel=tbs:table</span>"
          doesn't work with Ms Excel and Ms Powerpoint documents.</li>
        <li> Parameter "<span class="smallcode">parallel=tbs:table</span>" with
          OpenTBS will produce a wrong result if there is any cell with a merged
          style before of within the columns to merge with data using OpenTBS.</li>
      </ul>
      <p> See the <a href="http://www.tinybutstrong.com/manual.php#html_block_parallel">TBS
          manual</a> and the OpenTBS demo for more details about how to use
        parameter "<span class="smallcode">parallel</span>".</p>
      <p><span class="versioning">Parameter "parallel=tbs:table" is supported
          since OpenTBS version 1.8.2.</span></p>
      <h3><a id="mergecell"></a>4.8. Merge cells vertically</h3>
      Parameter "<span class="smallcode">ope=mergecell</span>" enables you to
      merge cells vertically in a table of an Ms Word Document.
      <p> Limitations:</p>
      <ul>
        <li>Parameter "<span class="smallcode">ope=mergecell</span>" doesn't
          work with LibreOffice.</li>
        <li> Parameter "<span class="smallcode">ope=mergecell</span>" will
          produce a wrong merge if there is any cell with a merged style before
          of within the columns to merge with data using OpenTBS.</li>
      </ul>
      <p>Parameter "<span class="smallcode">ope=mergecell</span>" can work only
        for a block merged on the rows of the table. Note that the TBS field
        with "<span class="smallcode">ope=mergecell</span>" does not display any
        value, it only produces the merge.</p>
      <div class="shift"> Example:
        <ul>
          <li><span class="template">[b.rank;block=tbs:row][b.rank;ope=mergecell]</span>
            =&gt; This will display the colmun rank and also merge the cells
            vertically depending on the rank.</li>
        </ul>
      </div>
      <p class="versioning">Parameter "ope=mergecell" is supported since OpenTBS
        version 1.8.0.</p>
      <h3><a id="cells"></a>4.9. Merging data in spreadsheet cells</h3>
      <p>In speaksheets (Ms Excel or LibreOffice Calc), cells values may be
        formated but also typed. For example, a cell value may be typed as
        String, Numerical, Boolean or Date.</p>
      <p>Unfortunately, as soon as you enter a TBS tag in a cell, the cell it is
        typed as String by the software. This may not be corresponding to the
        final value you wanted after the merging.</p>
      <p>For those situations, TBS offers a parameter like "<span class="smallcode">ope=cellType</span>".
        The cell type will be changed during the merging and the merged value
        will be implicitly converted by TBS to fit to the expected type.</p>
      <h5>Example:</h5>
      <ul>
        <li><span class="template">[onload.x;ope=tbs:num]</span> =&gt; will turn
          the cell as Numerical after $x is merged.</li>
      </ul>
      <h5>Parameters for merging data in spreadsheet cells:</h5>
      <table cellspacing="1" cellpadding="4" border="0">
        <tbody>
          <tr>
            <th align="left">Expected Cell Type</th>
            <th class="centered">Parameter</th>
            <th class="centered">Note</th>
          </tr>
          <tr>
            <td class="nowrap">Number</td>
            <td class="smallcode nowrap">ope=tbs:num</td>
            <td class="top smallcode nowrap">&nbsp;</td>
          </tr>
          <tr>
            <td class="nowrap">Boolean</td>
            <td class="smallcode nowrap">ope=tbs:bool</td>
            <td class="top smallcode nowrap">&nbsp;</td>
          </tr>
          <tr>
            <td class="nowrap">Date/time</td>
            <td class="smallcode nowrap">ope=tbs:date</td>
            <td class="top smallcode nowrap">&nbsp;</td>
          </tr>
          <tr>
            <td class="nowrap">Time only</td>
            <td class="smallcode nowrap">ope=tbs:time</td>
            <td class="nowrap">For XLSX, it's an alias of <span class="smallcode">ope=tbs:date</span></td>
          </tr>
          <tr>
            <td class="nowrap">Currency</td>
            <td class="smallcode nowrap">ope=tbs:curr</td>
            <td class="nowrap">
              <p>For XLSX, it's an alias of <span class="smallcode">ope=tbs:num</span></p>
            </td>
          </tr>
          <tr>
            <td class="nowrap">Percentage</td>
            <td class="smallcode nowrap">ope=tbs:percent</td>
            <td class="nowrap">For XLSX, it's an alias of <span class="smallcode">ope=tbs:num</span></td>
          </tr>
        </tbody>
      </table>
      <p class="versioning">The keywoks in the table above are supported since
        OpenTBS version 1.8.1.</p>
      <p class="versioning"> In previous version you should use keywords:
        odsNum, odsBool, odsDate, odsTime, odsCurr, odsPercent, xlsxNum,
        xlsxBool and xlsxDate.</p>
      <h3><a id="ranges"></a>4.10. Read and write ranges in a worksheet</h3>
      <p>• Read a range in a worksheet</p>
      <div class="shift"> <span class="versioning">(supported since OpenTBS
          version 1.10.0)</span>
        <div class="code">Example: $result = $TBS-&gt;PlugIn(OPENTBS_GET_CELLS,
          $RangeRef, $Options = array())</div>
        <p>This command returns an array containg all of the cell's values in a
          range of the workbook. </p>
        <p>Empty cells will have a NULL value.</p>
        <p>Cells with a formula will have the last value cached by the editor
          software (Calc or Excel). </p>
        <p>The reading is limited to the actual range of data in the sheet, not
          the theorical rows and colmuns in the range. For example, reading the
          range ''A:C' (which has theorically an infinit number of rows) will
          return only 3 rows if there is no more data after the third row.</p>
        <p>This command supports merged cells and also full columns and full
          rows. The result of full columns and full rows will be limited to the
          explicit data actually stored in the worksheet. </p>
        <table width="100%" cellspacing="1" cellpadding="4" border="0">
          <tbody>
            <tr>
              <th class="top" align="left">Argument</th>
              <th align="left">Description</th>
            </tr>
            <tr>
              <td class="top smallcode">
                <p>$<span class="code">RangeRef</span></p>
              </td>
              <td class="top">
                <p>It must be either :</p>
                <ul>
                  <li>An existing named range in the workbook. It can be a
                    global name, or name local to a worksheet.</li>
                  <li>An absolute range definition. That is a range that include
                    the worksheet name. The range definition must be compatible
                    with the formats (ODS or XLSX). Examples :
                    <ul>
                      <li>"$'my_sheet'.$A$2:$D$23"</li>
                      <li>"$'my_sheet'.$A:$D"</li>
                      <li>"$'my_sheet'.$8:$10"</li>
                    </ul>
                  </li>
                  <li>A local range definition. That is a range . Example :
                    "A1:D18". In this case the range taken in the worksheet
                    currently selected by OpenTBS.<br>
                  </li>
                </ul>
              </td>
            </tr>
            <tr>
              <td class="top smallcode">
                <p>$<span class="code">Options</span></p>
              </td>
              <td class="top">
                <ul>
                  <li><span class="smallcode">'header'</span> (<span class="smallcode">false</span>
                    by default) : indicate that the first row of the range
                    contains the header information and will be used as the
                    columns names for each returned rows.</li>
                  <li><span class="smallcode">'columns'</span> (<span class="smallcode">false</span>
                    by default) : an assocaitif array of columns to be renamed.
                    A missing index or a null value means the colum will not be
                    returned in the result.</li>
                  <li><span class="smallcode">'noerr'</span> (<span class="smallcode">false</span>
                    by default) : if this option is <span class="smallcode">true</span>
                    and the range cannot be found or read, then the function
                    return <span class="smallcode">false</span> without raising
                    an error.</li>
                  <li><span class="smallcode">'del_blank_rows'</span> (<span class="smallcode">false</span>
                    by default) : set this option to <span class="smallcode">'true</span>'
                    to not return blank rows. Note that blank rows after the
                    last actual row with data are never return anyway.</li>
                  <li><span class="smallcode">'row_max'</span> (<span class="smallcode">false</span>
                    by default) : the maximum number of row to return. <span class="smallcode">False</span>
                    means no limit.</li>
                  <li><span class="smallcode">'rangeinfo'</span> (<span class="smallcode">false</span>
                    by default) : set this option to <span class="smallcode">true</span>
                    in order to return the debug information about the range
                    definition instead of its data. For debuging purpose.</li>
                </ul>
              </td>
            </tr>
          </tbody>
        </table>
      </div>
      <p>• Write a range in a worksheet (<span class="versioning">Will be
          available in a next version</span>)</p>
      <h3><a name="docfield"></a>4.11. Merge document fields</h3>
      <p class="versioning">(Supported since OpenTBS version 1.10.0)</p>
      <p>Both DOCX and ODT files supports document fields that can be inserted
        anywhere in the document that is for example Mail Merge Fields.</p>
      <p class="shift">In Ms Word, document fields are available using: ribbon
        Insert / Text / Quick Parts / Field…<br>
        In LibreOffice, document fields are available using: menu Insert / Field
        / Other fields…</p>
      <p>For now, OpenTBS can replace only document fields whose type is <em>Conditional</em>.<br>
        For a DOCX, that is <em>IF</em> field.<br>
        For an ODT, that is <em>Fonction / Conditional text</em>.</p>
      <p>When you’ve <span lang="en"><span title="">positioned</span></span>
        your Conditional document field in your contents :</p>
      <ul>
        <li> in the placeholder for the condition, enter « <span class="smallcode">0
            = 1</span> » for a DOCX (the spaces are mandatory), or « <span class="smallcode">false</span>
          » for an ODT.</li>
        <li>use a TBS field with the parameter <span class="smallcode">ope=docfield</span>
          in the placeholder for THEN,</li>
        <li>enter any text in the placeholder for ELSE. This text will be
          displayed until the TBS fields is merged.</li>
      </ul>
      <p>When the TBS fields will be merged, the full document field will be
        deleted and replaced with the merged value.</p>
      <p>Limitations of parameter <span class="smallcode">"ope=docfield"</span>
        :</p>
      <ul>
        <li> It's taken into account only if a value is merged. I.e. it’s a TBS
          field's parameter, not a bock's parameter.</li>
        <li>Other TBS fields in the document field will be deleted.</li>
      </ul>
      <p>Example with DOCX:</p>
      <p class="shift code">IF 1 = 0 "[onshow.x_num;ope=docfield;frm=0,000.00]"
        "XX.XX"</p>
      <p>Example with ODT:</p>
      <p class="shift code">Conditional text false
        [onshow.x_num;ope=docfield;frm=0,000.00] XX.XX</p>
      <p>See the demo DOC and ODT for more details.</p>
      <h3><a id="other_commands"></a>4.12. Other merging commands</h3>
      <p><span class="versioning">The following commands are supported since
          OpenTBS version 1.7.0 </span>:</p>
      <table cellspacing="1" cellpadding="4" border="0">
        <tbody>
          <tr>
            <th align="left">Command</th>
            <th align="left">Description</th>
          </tr>
          <tr>
            <td class="top nowrap category centered"><span class="smallcode"><a
                  id="commands_for_all"></a></span>For all types of documents</td>
            <td class="top">&nbsp;</td>
          </tr>
          <tr>
            <td class="top nowrap"><span class="smallcode"><a id="opentbs_select_main"></a>$TBS-&gt;PlugIn(OPENTBS_SELECT_MAIN)</span></td>
            <td class="top">
              <p>Select and load the main sub-file in the opened template. For
                example in a Writer document, or an Ms Word document, this
                command can bring you back from the merging of a header to the
                main body.</p>
            </td>
          </tr>
          <tr>
            <td class="top nowrap"><span class="smallcode"><a id="opentbs_select_file"></a>$TBS-&gt;PlugIn(OPENTBS_SELECT_FILE,
                $SubFile)</span></td>
            <td class="top">
              <p>Select a sub-file in the opened template. Return <span class="smallcode">false</span>
                if the sub-file is not found. If the sub- file is stored in a
                subfolder, then indicate the full path. For example:
                'word/document.xml'.</p>
              <p>Before OpenTBS 1.9.0, selecting a sub-file had to be done using
                <span class="smallcode">$TBS-&gt;LoadTemplate('#' . $SubFile);.</span></p>
              <p><span class="versioning">Command OPENTBS_SELECT_FILE is
                  supported since OpenTBS version 1.9.0.</span></p>
            </td>
          </tr>
          <tr>
            <td class="top nowrap">
              <p><a id="opentbs_change_picture"></a><span class="smallcode">$TBS-&gt;PlugIn(OPENTBS_CHANGE_PICTURE,
                  $PicRef, $File [, $Prms])</span><br>
              </p>
              <p>&nbsp;</p>
              <p>Deprecated:</p>
              <p><span class="smallcode"><em>$TBS-&gt;PlugIn(OPENTBS_CHANGE_PICTURE,
                    $PicRef, $File<br>
                    [, $Default]<br>
                    [, $Adjust]<br>
                    ) </em></span></p>
            </td>
            <td valign="top">
              <p class="warning">Does not work with XLSX yet.</p>
              <p>Change one or several pictures in the current sub-file. This
                command does the same as the <a href="#pic">changepic</a>
                feature. The difference is that the command needs no TBS tags in
                the template.</p>
              <ul>
                <li> <span class="smallcode">$PicRef</span> must be a string
                  that is saved in the Title or the Description of the picture.
                  If several pictures have the same key string then they are all
                  replaced with the picture. It won't work if you put the string
                  reference tag inside the property Name of an image in
                  LibreOffice/OpenOffice. In Ms Word 2007, both properties
                  Description and Title are supported but not available for
                  editing, but you can use "Alternative text" (in the "Web" tab
                  of the Size dialog box) , ot the URL, or the Toolipt of a Link
                  on the image.</li>
                <li><span class="smallcode">$File</span> must be path for
                  picture file that will be copied inside the document.</li>
                <li><span class="smallcode">$Prms</span> can be an associated
                  array of parameters supported by parameter <a href="#pic">changepic</a>.</li>
              </ul>
              <p>Example: </p>
              <p><span class="smallcode">$prms = array('unique' =&gt; true);<br>
                  $TBS-&gt;Plugin(OPENTBS_CHANGE_PICTURE, '#main_map#',
                  'pics/new_map.png', $prms); </span></p>
              <span class="versioning">Command OPENTBS_CHANGE_PICTURE is
                supported since OpenTBS version 1.8.0.<br>
                Parameter $Prms is supported since version 1.9.1.</span></td>
          </tr>
          <tr>
            <td class="top smallcode nowrap"><a id="opentbs_get_files_by_type"></a>$TBS-&gt;PlugIn(OPENTBS_GET_FILES_BY_TYPE,
              $Types)</td>
            <td valign="top">
              <p>Return an array of all sub-files corresponding to the asked
                types. </p>
              <p> <span class="smallcode">$Types</span> must be a string or an
                array of strings, supported values are:</p>
              <ul>
                <li class="smallcode">'main'</li>
                <li class="smallcode">'header'</li>
                <li class="smallcode">'footer'</li>
                <li class="smallcode">'chart'</li>
                <li class="smallcode">'comments'</li>
                <li class="smallcode">'sheet'</li>
                <li class="smallcode">'slide'</li>
                <li class="smallcode">'slidem' (for slide master)</li>
                <li class="smallcode">'all' (for all above)</li>
              </ul>
              <p class="code">// Example<br>
                $subfile_lst = $TBS-&gt;PlugIn(OPENTBS_GET_FILES_BY_TYPE,
                ['charts']);</p>
              <span class="versioning">Command OPENTBS_GET_FILES_BY_TYPE is
                supported since OpenTBS version 1.12.0. </span></td>
          </tr>
          <tr>
            <td class="top smallcode nowrap"><a id="opentbs_delete_comments"></a>$TBS-&gt;PlugIn(OPENTBS_DELETE_COMMENTS)</td>
            <td valign="top">
              <p>Delete all usual user comments in the opened template. </p>
            </td>
          </tr>
          <tr>
            <td class="top nowrap"><span class="smallcode"><a id="opentbs_delete_elements"></a>$TBS-&gt;PlugIn(OPENTBS_DELETE_ELEMENTS,
                $Elements)</span></td>
            <td valign="top">
              <p>Delete XML elements in the current sub-file.</p>
              <p> <span class="smallcode">$Elements</span> must be an array of
                strings.</p>
              <p> For example: <span class="smallcode">$Elements =
                  array('w:bookmarkStart', 'w:bookmarkEnd')</span> This will
                delete all bookmarks in an Ms Word document. </p>
            </td>
          </tr>
          <tr>
            <td class="top nowrap"><span class="smallcode"><a id="opentbs_add_credit"></a>$TBS-&gt;PlugIn(OPENTBS_ADD_CREDIT,
                $Text [, $Name])</span></td>
            <td valign="top">
              <p>Add a new credit text in the properties of the document. </p>
              <p>For LibreOffice/OpenOffice, this will add the text as a new
                Custom Property of the document. You can use argument <span class="smallcode">$Name</span>
                for the custom property's name.</p>
              <p>For Ms Office, this will add the text in the Author property of
                the document. You can use argument <span class="smallcode">$Name</span>
                to specify another XML element for placing the text. Exemple : <span
                  class="smallcode">'dc:description'</span> will add the text in
                the Comment property. Take care that using an unsupported value
                can corrupt the document.</p>
              <p><span class="versioning">Command OPENTBS_ADD_CREDIT is
                  supported since OpenTBS version 1.9.1.</span></p>
            </td>
          </tr>
          <tr>
            <td class="top nowrap"><span class="smallcode"><a id="opentbs_system_credit"></a>$TBS-&gt;PlugIn(OPENTBS_SYSTEM_CREDIT,
                $Enable)</span></td>
            <td valign="top">
              <p>Enable or disable the System Credit. System Credit add the
                current version of OpenTBS into a creator property of the
                document. The System Credit is enabled by default.</p>
              <p><span class="versioning">Command OPENTBS_SYSTEM_CREDIT is
                  supported since OpenTBS version 1.9.1.</span></p>
            </td>
          </tr>
          <tr>
            <td class="top nowrap"><span class="smallcode"><a name="opentbs_read_entity"
                  id="opentbs_edit_entity2"></a>$TBS-&gt;PlugIn(OPENTBS_READ_ENTITY,
                $SubFile<br>
                , $ElPath, $Att)</span></td>
            <td valign="top">
              <p>Retrieve an attribute's value or an entity's value in the first
                element in a given sub-file. Return the asked value, or <span class="smallcode">
                  false</span> if the attribute or the entity is not found. Also
                retrurn <span class="smallcode">false</span> if an entity’s
                value is asked while the entity is a self-closed tag.</p>
              <ul>
                <li><span class="smallcode">$SubFile</span> (string|boolean):
                  the name or the index of the sub-file. Use value <span class="smallcode">false</span>
                  to get the current sub-file.</li>
                <li> <span class="smallcode">$ElPath</span> (string): path of
                  the element. For example : <span class="smallcode">'w:document/w:body/w:p'</span>.
                  Sub-entities are optional but can remove ambiguities.</li>
                <li> <span class="smallcode">$Att</span> (string|boolean): the
                  attribute, or <span class="smallcode">false</span> to replace
                  the entity's value.</li>
              </ul>
              <p><span class="versioning">Command OPENTBS_READ_ENTITY is
                  supported since OpenTBS version 1.10.3.</span></p>
            </td>
          </tr>
          <tr>
            <td class="top nowrap"><span class="smallcode"><a id="opentbs_edit_entity"></a>$TBS-&gt;PlugIn(OPENTBS_EDIT_ENTITY,
                $SubFile<br>
                , $ElPath, $Att, $NewVal, $AddElIfMissing = false)</span></td>
            <td valign="top">
              <p>Change an attribute's value or an entity's value in the first
                element in a given sub-file. Return <span class="smallcode">true</span>
                if the attribute is found and processed, <span class="smallcode">
                  false</span> otherwise.</p>
              <ul>
                <li><span class="smallcode">$SubFile</span> (string|boolean):
                  the name or the index of the sub-file. Use value <span class="smallcode">false</span>
                  to get the current sub-file.</li>
                <li> <span class="smallcode">$ElPath</span> (string): path of
                  the element. For example : <span class="smallcode">'w:document/w:body/w:p'</span>.
                  Sub-entities are optional but can remove ambiguities.</li>
                <li> <span class="smallcode">$Att</span> (string|boolean): the
                  attribute, or <span class="smallcode">false</span> to replace
                  the entity's value.</li>
                <li> <span class="smallcode">$NewVal</span> (string|boolean):
                  the new value, or <span class="smallcode">false</span> to
                  delete the attribute.</li>
              </ul>
              <p><span class="versioning">Command OPENTBS_EDIT_ENTITY is
                  supported since OpenTBS version 1.9.5.</span></p>
            </td>
          </tr>
          <tr>
            <td class="top nowrap category centered"><span class="smallcode"><a
                  id="commands_for_documents"></a></span>For documents (ODT and
              DOCX)</td>
            <td valign="top">&nbsp;</td>
          </tr>
          <tr>
            <td class="top smallcode nowrap"><a id="opentbs_select_header"></a>$TBS-&gt;PlugIn(OPENTBS_SELECT_HEADER,
              [$Type[, $Offset])<br>
              <a id="opentbs_select_footer"></a>$TBS-&gt;PlugIn(OPENTBS_SELECT_FOOTER,
              [$Type[, $Offset])</td>
            <td valign="top">
              <p>Select the sub-file corresponding to the header of the footer.
                Return <span class="smallcode">true</span> if succeed, <span class="smallcode">false</span>
                if it fails.</p>
              <p>For LibreOffice/OpenOffice, headers and footer are saved in the
                same sub-file. For ODS and ODP, the sub-file containing headers
                and footer is the main file.</p>
              <p>For XLSX and PPTX this command will always return <span class="smallcode">false</span>
                because headers and footers are saved in sheets or slides.</p>
              For DOCX, they may have several headers or footers in the same
              document. Eeach section can have its own set of typed header and
              footer :
              <div class="shift">
                <ul>
                  <li> a default header (or footer)</li>
                  <li> an optional header (or footer) for the first page of the
                    section</li>
                  <li> an optional header (or footer) for even pages of the
                    section</li>
                </ul>
                <p>In order to select a specific header or footer, you have to
                  use the arguments <span class="smallcode">$Type</span> and <span
                    class="top smallcode nowrap">$Offset</span>.</p>
                <ul>
                  <li><span class="smallcode">$Type</span> can be :
                    OPENTBS_DEFAULT (default value), OPENTBS_FIRST, or
                    OPENTBS_EVEN.</li>
                  <li><span class="smallcode">$Offset</span> (default value is <span
                      class="smallcode">0</span>) is used to select the typed
                    header or footer of another section.</li>
                </ul>
                <p>If you wan to select all the sections of the document, then
                  see command <span class="top smallcode nowrap"><a href="#opentbs_get_headers_footers">OPENTBS_GET_HEADERS_FOOTERS</a></span>.</p>
              </div>
              <p class="versioning">Command OPENTBS_SELECT_HEADER and
                OPENTBS_SELECT_FOOTER are supported since OpenTBS version 1.9.0.</p>
            </td>
          </tr>
          <tr>
            <td class="top smallcode nowrap"><a id="opentbs_get_headers_footers"></a>$TBS-&gt;PlugIn(OPENTBS_GET_HEADERS_FOOTERS)</td>
            <td valign="top">
              <p>Return an array of all sub-files that are headers and footers
                of the document.</p>
              <p>See also command <span class="top smallcode nowrap"><a href="#opentbs_get_files_by_type">OPENTBS_GET_FILES_BY_TYPE</a></span>.</p>
              <div class="code">// Example<br>
                $subfile_lst = $TBS-&gt;PlugIn(OPENTBS_GET_HEADERS_FOOTERS);<br>
                foreach ($subfile_lst as $subfile) {<br>
                &nbsp;&nbsp;$TBS-&gt;PlugIn(OPENTBS_SELECT_FILE, $subfile);<br>
                &nbsp;&nbsp;$TBS-&gt;MergeField('f', $info);<br>
                }</div>
              <p class="versioning">Command OPENTBS_GET_HEADERS_FOOTERS is
                supported since OpenTBS version 1.9.0.</p>
            </td>
          </tr>
          <tr>
            <td class="nowrap category centered" valign="top"><span class="smallcode"><a
                  id="commands_for_workbooks"></a></span>For workbooks (ODS and
              XLSX)</td>
            <td valign="top">&nbsp;</td>
          </tr>
          <tr>
            <td class="top smallcode nowrap"><a id="opentbs_select_sheet"></a>$TBS-&gt;PlugIn(OPENTBS_SELECT_SHEET,
              $NumOrName [, $ById])</td>
            <td valign="top">
              <p>Select the sub-file corresponding to <span class="smallcode">$NumOrName</span>.
                This command will raise an error if the opened template is not
                an expected document.</p>
              <p>This command is useless for LibreOffice/OpenOffice because all
                sheets/slides are all saved in the main sub-file. Nevertheless
                using it will select the main sub-file without raising an error.</p>
              <p><span class="smallcode">$NumOrName</span> is an identifier that
                can be either an integer corresponding to the number of the
                sheet in the sheet list (first is number 1), or a string
                corresponding to the name of the sheet.</p>
              <p>Use command <span class="smallcode">$TBS-&gt;PlugIn(<a href="#debugmode">OPENTBS_DEBUG_INFO</a>)</span>
                to list all id and name of sheets/slides in the current
                document.</p>
              <p>Use command <span class="smallcode">$TBS-&gt;PlugIn(<a href="#opentbs_count_sheets">OPENTBS_COUNT_SHEETS</a>)</span>
                get the number of sheets in the workbook.</p>
              <p><span class="smallcode">$ById</span> is false by default, set
                it to <span class="smallcode">true</span> if you want to select
                the sheet by its internal ID instead of its number in the sheet
                list. This can be used for compatibility with previous OpenTBS
                vesions (see version history below). </p>
              <p class="versioning">Command OPENTBS_SELECT_SHEET is supported
                since OpenTBS version 1.8.0.<br>
                Argument $ById is supported since OpenTBS version 1.9.6.<br>
                Before OpenTBS version 1.9.6, the sheet was not find by its
                number in the sheet list but only by its internal id, which may
                be different. </p>
            </td>
          </tr>
          <tr>
            <td class="top smallcode nowrap"><a id="opentbs_display_sheet"></a>$TBS-&gt;PlugIn(OPENTBS_DISPLAY_SHEETS,
              $NumOrNames[, $Visible])</td>
            <td valign="top">
              <p>Make one or several sheets/slides visible or hidden. This
                command will raise an error if the opened template is not an
                expected document.</p>
              <ul>
                <li> <span class="smallcode">$NumOrNames</span> must be an
                  array of identifiers, or even a single identifier. See command
                  <span class="smallcode">OPENTBS_SELECT_SHEET</span> for more
                  details about identifiers.</li>
                <li><span class="smallcode">$Visible</span> must be a boolean,
                  default value is <span class="smallcode">true</span>.</li>
              </ul>
              <p><span class="versioning">Command OPENTBS_DISPLAY_SHEETS is
                  supported since OpenTBS version 1.8.0.</span><br>
                <span class="versioning">Before OpenTBS version 1.9.6, the sheet
                  was not selected by its number in the sheet list but only by
                  its internal id, which may be different. </span> </p>
            </td>
          </tr>
          <tr>
            <td class="top smallcode nowrap"><a id="opentbs_delete_sheets"></a>$TBS-&gt;PlugIn(OPENTBS_DELETE_SHEETS,
              $NumOrNames[, $Delete])</td>
            <td valign="top">
              <p>Make one or several sheets te be deleted or not. This command
                will raise an error if the opened template is not a Workbook.</p>
              <ul>
                <li> <span class="smallcode">$NumOrNames</span> must be an
                  array of identifiers, or even a single identifier. See command
                  <span class="smallcode">OPENTBS_SELECT_SHEET</span> for more
                  details about identifiers.</li>
                <li><span class="smallcode">$Delete</span> must be a boolean,
                  default value is <span class="smallcode">true</span>.</li>
              </ul>
              <p><em class="warning">Please note that for now, you must not
                  delete a sheet that contains a Pivot Table in a XLSX workbook
                  because this will produce an error when the workbook is
                  opened.</em></p>
              <p><span class="versioning">Command OPENTBS_DELETE_SHEETS is
                  supported since OpenTBS version 1.8.0.</span><br>
                <span class="versioning">Before OpenTBS version 1.9.6, the sheet
                  was not find by its number in the sheet list but only by its
                  internal id, which may be different. </span> </p>
            </td>
          </tr>
          <tr>
            <td class="top smallcode nowrap"><a id="opentbs_count_sheets"></a>$TBS-&gt;PlugIn(OPENTBS_COUNT_SHEETS)</td>
            <td valign="top">
              <p>Return the number of sheets in the workbook. Always return 0 if
                the document is neither an XLSX nor an ODS. </p>
              <p> <span class="versioning">Command OPENTBS_COUNT_SHEETS is
                  supported since OpenTBS version 1.9.1.</span></p>
            </td>
          </tr>
          <tr>
            <td class="top smallcode nowrap"><a id="opentbs_merge_special_items"></a>$TBS-&gt;PlugIn(OPENTBS_MERGE_SPECIAL_ITEMS)</td>
            <td valign="top">
              <p>Merge special items relatively to the current sub-file. For
                now, it has effect only with Ms Excel workbooks. This command
                makes automatic fields ([onload] and [onshow]) merged in
                pictures embedded in the current selected sheet. This can be
                useful for changing pictures in Ms Excel.</p>
              <p> <span class="versioning">Command OPENTBS_MERGE_SPECIAL_ITEMS
                  is supported since OpenTBS version 1.8.0.</span></p>
            </td>
          </tr>
          <tr>
            <td class="top nowrap"><span class="smallcode"><a id="opentbs_relative_cells"></a>$TBS-&gt;PlugIn(OPENTBS_RELATIVE_CELLS,
                $Enabled[, $Options])</span></td>
            <td valign="top">
              <p>This command may significatively optimize time generation for
                XLSX workbooks that contains sheets with large numerous rows. By
                default the Ms Excel software saves sheets with explicit cells
                positioning, and OpenTBS has the same behavior by default. This
                operation may be quite slowing OpenTBS for sheets with large
                numerous rows. In another hand saving sheets with relative cells
                positioning is quite faster and the final file may be smaller.
                Use this command in order to define the saving behavior about
                cells.</p>
              <ul>
                <li> <span class="smallcode">$Enabled</span> set to <span class="smallcode">true</span>
                  in order to activate the relative cells positioning for the
                  current sheet only.</li>
                <li><span class="smallcode">$Options </span> set to <span class="smallcode">OPENTBS_ALL</span>
                  in order to apply the command to all sheets in the current
                  workbook.</li>
              </ul>
              <p> This command has no effects for other documents type than XLSX
                workbooks. </p>
              <p> <span class="versioning">Command OPENTBS_RELATIVE_CELLS is
                  supported since OpenTBS version 1.9.2.</span></p>
            </td>
          </tr>
          <tr>
            <td class="nowrap category" align="center" valign="top"> <span class="smallcode"><a
                  id="commands_for_presentations"></a></span>For presentations
              (ODP and PPTX)</td>
            <td valign="top">&nbsp;</td>
          </tr>
          <tr>
            <td class="top smallcode nowrap"><a id="opentbs_select_slide"></a>$TBS-&gt;PlugIn(OPENTBS_SELECT_SLIDE,
              $NumOrName[, $Master])</td>
            <td valign="top">
              <p>Same as command <a href="#opentbs_select_sheet">OPENTBS_SELECT_SHEET</a>
                but for slides.</p>
              <p><span class="smallcode">$Master </span>is a boolean to
                indicate if you want to select a master slide in the document.
                Default value is <span class="smallcode">false</span>.</p>
              <p><span class="versioning">Command OPENTBS_SELECT_SLIDE is
                  supported since OpenTBS version 1.8.0.<br>
                  Argument $Master is supported since OpenTBS version 1.9.0.</span></p>
            </td>
          </tr>
          <tr>
            <td class="top smallcode nowrap"> <a id="opentbs_display_slide"></a>$TBS-&gt;PlugIn(OPENTBS_DISPLAY_SLIDES,
              $NumOrNames[, $Visible])</td>
            <td valign="top">
              <p>Same as command <a href="#opentbs_display_sheet">OPENTBS_DISPLAY_SHEET</a>
                but for slides.</p>
            </td>
          </tr>
          <tr>
            <td class="top smallcode nowrap"><a id="opentbs_delete_slides"></a>$TBS-&gt;PlugIn(OPENTBS_DELETE_SLIDES,
              $NumOrNames[, $Delete])</td>
            <td valign="top">
              <p>Same as command <a href="#opentbs_delete_sheets">OPENTBS_DELETE_SHEETS</a>
                but for slides.</p>
            </td>
          </tr>
          <tr>
            <td class="top smallcode nowrap"><a id="opentbs_count_slides"></a>$TBS-&gt;PlugIn(OPENTBS_COUNT_SLIDES[,
              $Master])</td>
            <td valign="top">
              <p>Return the number of slides in the presentation. Always return
                0 if the document is neither a PPTX nor an ODP.</p>
              <p><span class="smallcode">$Master </span>is a boolean to
                indicate if you want to count master slides in the document.
                Default value is <span class="smallcode">false</span>.</p>
              <p> <span class="versioning">Command OPENTBS_COUNT_SLIDES is
                  supported since OpenTBS version 1.8.0.</span><br>
                <span class="versioning">Argument $Master is supported since
                  OpenTBS version 1.9.0.</span> </p>
            </td>
          </tr>
          <tr>
            <td class="top smallcode nowrap"><a id="opentbs_search_in_slides"></a>$TBS-&gt;PlugIn(OPENTBS_SEARCH_IN_SLIDES,
              $Str[, $Options])</td>
            <td valign="top">
              <p>Search for the string <span class="smallcode">$Str</span>
                trough the slides of the current document. Return the id of the
                first slide where the string is found. Return <span class="smallcode">false</span>
                if the string is not found.</p>
              <p><span class="smallcode">$Options</span> must be a combination
                of the following constants. Default value is OPENTBS_FIRST. </p>
              <ul>
                <li>OPENTBS_FIRST : stop the search at the first slide where the
                  string is found.</li>
                <li>OPENTBS_GO : select the corresponding slide if the string is
                  found.</li>
                <li>OPENTBS_ALL : search through all slides and return an array
                  of the slide ids.</li>
              </ul>
              <p>This command is useless for LibreOffice/OpenOffice because all
                slides are all saved in the main sub-file. Nevertheless using
                will not raise an error.</p>
              <p><span class="versioning">Command OPENTBS_SEARCH_IN_SLIDES is
                  supported since OpenTBS version 1.9.0.</span></p>
            </td>
          </tr>
        </tbody>
      </table>
      <h3><a id="modify_files"></a>4.13. Manage files in the archive</h3>
      <h4 style="display:inline">• Get all files in the archive:</h4>
      <div class="shift">
        <div class="code">$TBS-&gt;Plugin(OPENTBS_GET_FILES)</div>
        <p>Return the list of all files in the archive.</p>
        <p>See also command <span class="top smallcode nowrap"><a href="#opentbs_get_files_by_type">OPENTBS_GET_FILES_BY_TYPE</a></span>.</p>
        <div class="versioning">(supported since OpenTBS version 1.9.7)</div>
      </div>
      <h4 style="display:inline">&nbsp;</h4>
      <h4 style="display:inline">&nbsp;</h4>
      <h4 style="display:inline">&nbsp;</h4>
      <h4 style="display:inline">&nbsp;</h4>
      <h4 style="display:inline">&nbsp;</h4>
      <h4 style="display:inline">• Get all files in the archive:</h4>
      <div class="shift">
        <div class="code">$TBS-&gt;Plugin(OPENTBS_GET_OPENED_FILES)</div>
        <p>Return the list of all files in the archive that has been already
          loaded for a TBS merge. This includes all files that you manually
          loaded using command OPENTBS_SELECT_FILE, but also all files loaded
          automatically by OpenTBS such as the main file, or modified charts, or
          sometimes headers and footers. Some technical files that are modified
          by OpenTBS in back-end but cannot contain TBS fields (such as manifest
          files or relation files) are not returned by this command.</p>
        <div class="versioning">(supported since OpenTBS version 1.9.11)</div>
      </div>
      <h4></h4>
      <h4 style="display:inline">• Get all files in the archive:</h4>
      <div class="shift">
        <div class="code">$TBS-&gt;Plugin(OPENTBS_WALK_OPENED_FILES, $callable)</div>
        <p>Apply a user supplied function to every file in the archive that has
          been already loaded for a TBS merge (see command <span class="code">OPENTBS_GET_OPENED_FILES</span>).</p>
        <p>Argument <span class="smallcode">$callable</span> must be a <a href="http://php.net/manual/en/language.types.callable.php"
            target="_blank">callable function</a> with one or two arguments: the
          editable content of the file being the first, and file's name the
          second.</p>
        <pre class="code">// Example:
$user_func = array($my_object, 'translate');
$TBS-&gt;Plugin(OPENTBS_WALK_OPENED_FILES, $user_func);</pre>
        <div class="versioning">(supported since OpenTBS version 1.9.11)</div>
      </div>
      <h4>• Check if a file does exists in the archive:</h4>
      <div class="shift">
        <div class="code">$TBS-&gt;Plugin(OPENTBS_FILEEXISTS, $Name)</div>
        <p>Return <span class="smallcode">true</span> or <span class="smallcode">false</span>.
          $Name must include the inner path. For example : <span class="smallcode">$Name
            = 'META-INF/manifest.xml';</span></p>
        <div class="versioning">(supported since OpenTBS version 1.7.4)</div>
      </div>
      <h4>• Add any new file in the archive:</h4>
      <div class="shift">
        <pre class="code">// OpenTBS &gt;= 1.6.0
$TBS-&gt;Plugin(OPENTBS_ADDFILE, $Name, $Data, $DataType=OPENTBS_STRING, $Compress=true);

// Deprecated since OpenTBS 1.6.0
$TBS-&gt;Plugin(OPENTBS_PLUGIN, OPENTBS_ADDFILE, $Name, $Data, $DataType=OPENTBS_STRING, $Compress=true);  </pre>
        <p> If $Data is false then the previously add file with the given name
          is canceled if any.</p>
        <p> $DataType must be <span class="smallcode">OPENTBS_STRING</span> if
          $Data is the content to add ; it must be <span class="smallcode">OPENTBS_FILE</span>
          if $Data is the path of the external file to insert.</p>
        <p> $Compress can be true, false or an array with keys
          ('meth','len_u','crc32') which means that the data is already
          previously compressed.</p>
        <div class="versioning">(supported since OpenTBS version 1.3)</div>
      </div>
      <h4>• Replace an existing file in the archive:</h4>
      <div class="shift">
        <div class="code">$TBS-&gt;Plugin(OPENTBS_REPLACEFILE, $Name, $Data,
          $DataType=OPENTBS_STRING, $Compress=true); </div>
        <p>The arguments are the same as command <span class="smallcode">OPENTBS_ADDFILE</span>.</p>
        <p> Please note that any TBS merge on a file in the archive will cancel
          previous or future replacements.</p>
        <div class="versioning">(supported since OpenTBS version 1.7.4)</div>
      </div>
      <h4>• Delete an existing file in the archive:</h4>
      <div class="shift">
        <pre class="code">// OpenTBS &gt;= 1.6.0
$TBS-&gt;Plugin(OPENTBS_DELETEFILE, $Name);

// Deprecated since OpenTBS 1.6.0
$TBS-&gt;Plugin(OPENTBS_PLUGIN, OPENTBS_DELETEFILE, $Name);</pre>
        <p>Delete the existing file in the archive, or a file previously added
          using the <span class="smallcode">OPENTBS_ADDFILE</span> command.</p>
        <div class="versioning">(supported since OpenTBS version 1.3)</div>
      </div>
      <h4>• Reset all modifications in the archive:</h4>
      <div class="shift">
        <pre class="code">// OpenTBS &gt;= 1.6.0
$TBS-&gt;Plugin(OPENTBS_RESET);

// Deprecated since OpenTBS 1.6.0
$TBS-&gt;Plugin(OPENTBS_PLUGIN, OPENTBS_RESET);</pre>
        <p>The automatic extension recognition is also applied as it was applied
          for the first load of the archive.</p>
      </div>
      <h3><a id="special_options"></a>4.14. Special options</h3>
      <h4>Dealing with apostrophes:</h4>
      <div class="shift">
        <p> Both OpenOffice and Ms Office may automatically convert single
          quotes (') into typographic apostrophes (’), depending to the
          auto-correction options. This may be annoying when you need to code a
          TBS fields that have a single quote. That's why OpenTBS automatically
          convert by default all (’) back to single quotes (') in documents.</p>
        <p> If you want to stop this conversion, you can set <span class="smallcode">$TBS-&gt;OtbsConvertApostrophes
            = false;</span> and no apostrophes will be converted. Note that you
          can avoid the auto-correction of single quotes (') in Ms Word using
          keys[ctrl]+[z], and in OpenOffice using the cancel button. </p>
        <div class="versioning">Property OtbsConvertApostrophes is supported
          since OpenTBS version 1.6.0.</div>
      </div>
      <h4><a id="force_doctype2"></a>•Make an optimized version of a template:</h4>
      <div class="shift">
        <p>Some template can be long to load because OpenTBS has to cleanup or
          prepare somes sub-files. There is a command that save a template as a
          new template file which is already prepared for OpenTBS, thus loading
          it will be faster.</p>
        <div class="code"> $TBS-&gt;Plugin(OPENTBS_MAKE_OPTIMIZED_TEMPLATE,
          $template, $new_template);</div>
        <p class="versioning">This command is supported since OpenTBS version
          1.9.8.</p>
      </div>
      <h4><a id="force_doctype"></a>• Forcing the document type recognition:</h4>
      <div class="shift">
        <p>You can force the document type recognition using command
          OPENTBS_FORCE_DOCTYPE. Example:</p>
        <div class="code"> $TBS-&gt;PlugIn(OPENTBS_FORCE_DOCTYPE, 'docx');</div>
        <p class="versioning">This command is supported since OpenTBS version
          1.6.0.</p>
      </div>
      <h4>• Retrieving the name of the current document:</h4>
      <div class="shift">
        <p> Property <span class="smallcode">$TBS-&gt;tbsCurrFile</span>
          indicates the name of the current file loaded from the archive. The
          value is false if no file is loaded yet from the archive.</p>
        <p> Other TinyButStrong methods and properties stay unchanged and are
          available for merging your template. </p>
        <div class="versioning">(supported since OpenTBS version 1.1)</div>
      </div>
      <h2><a id="demo"></a>5. Demo</h2>
      <p>The OpenTBS package includes a full set of runnable templates. Some
        templates can contain useful complementary information for designing.</p>
      <p> You can test the demo at the web site: <a href="http://www.tinybutstrong.com/plugins/opentbs/demo">OpenTBS
          demo</a></p>
      <h2><a id="debug"></a>6. Debugging your template</h2>
      <p><a id="debugmode"></a>Since OpenTBS version 1.6.0, there are several
        commands for debugging. Please note that those commands do not exit the
        process.</p>
      <table cellspacing="1" cellpadding="0" border="0">
        <tbody>
          <tr>
            <th align="left">Command</th>
            <th align="left">Desciption</th>
          </tr>
          <tr>
            <td class="top smallcode nowrap">$TBS-&gt;PlugIn(OPENTBS_DEBUG_INFO
              [, $Exit])</td>
            <td>Display technical information about the current loaded template,
              including sheet information if the template is a workbook, and
              chart information if the template have some.<br>
              <span class="smallcode">$Exit</span> must be a boolean, default
              value is <span class="smallcode">true</span>.</td>
          </tr>
          <tr>
            <td class="top smallcode nowrap">$TBS-&gt;PlugIn(OPENTBS_DEBUG_XML_CURRENT
              [, $Exit])</td>
            <td>Display XML contents of sub-files already opened and modified
              for merging. XML is indented in order to improve reading.<br>
              <span class="smallcode">$Exit</span> must be a boolean, default
              value is <span class="smallcode">true</span>.</td>
          </tr>
          <tr>
            <td class="top smallcode nowrap">$TBS-&gt;PlugIn(OPENTBS_DEBUG_XML_SHOW)</td>
            <td>Ends the merge process as if the final document was created. But
              instead of creating the document, displays the XML contents of
              sub-files modified for merging. XML is indented in order to
              improve reading.</td>
          </tr>
        </tbody>
      </table>
      <p>There is also <strong>deprecated</strong> debug options:</p>
      <table cellspacing="1" cellpadding="0" border="0">
        <tbody>
          <tr>
            <th align="left">Command</th>
            <th align="left">Desciption</th>
          </tr>
          <tr>
            <td class="top smallcode nowrap">$TBS-&gt;Show(OPENTBS_DEBUG_XML)</td>
            <td>Does the same as <span class="smallcode">$TBS-&gt;PlugIn(OPENTBS_DEBUG_XML_SHOW);</span><span
                class="versioning">Supported since OpenTBS version 1.3.2.</span></td>
          </tr>
          <tr>
            <td class="top smallcode nowrap">$TBS-&gt;Show(OPENTBS_DEBUG_XML+OPENTBS_DEBUG_AVOIDAUTOFIELDS)</td>
            <td>Avoid merging of [onload], [onshow] and [var].<span class="versioning">Supported
                since OpenTBS version 1.3.2.</span></td>
          </tr>
          <tr>
            <td class="top smallcode nowrap">$TBS-&gt;Render =
              OPENTBS_DEBUG_AVOIDAUTOFIELDS;</td>
            <td> Work also in property Render.<span class="versioning">Supported
                since OpenTBS version 1.3.2.</span></td>
          </tr>
          <tr>
            <td class="top smallcode nowrap">$TBS-&gt;PlugIn(OPENTBS_DEBUG_CHART_LIST)</td>
            <td>Does the same as <span class="smallcode">$TBS-&gt;PlugIn(OPENTBS_DEBUG_INFO);</span><span
                class="versioning">Supported since OpenTBS version 1.6.0.</span></td>
          </tr>
        </tbody>
      </table>
      <p>Otherwise, here are some indications that may help for the issues you
        can met with merging:</p>
      <h3><a id="debug_error"></a>a) The merged document is producing error
        messages when opened with its application (OpenOffice or Ms Office)</h3>
      <p>The most likely causes are:</p>
      <p>• You've chosen the <span class="smallcode">OPENTBS_DOWNLOAD</span>
        render option but a php error message or any other unexpected content
        has been output before by PHP.</p>
      <p class="shift">Activate the <a href="#debugmode">debug mode</a> using
        the command <span class="smallcode">OPENTBS_DEBUG_XML_SHOW</span>, it
        helps to check PHP error message and other unexpected content.</p>
      <p>• The merging has produced an invalid document or an invalid XML
        content in an XML file of the document.</p>
      <p class="shift">Activate the <a href="#debugmode">debug mode</a> using
        it helps to check the XML contents of merged files.</p>
      <p> See section (b) below for more information in the XML structure of the
        files.</p>
      <h3><a id="debug_tags"></a>b) Some TBS tags are not merged</h3>
      <p>First be sure that the TBS tag is a in a part of the document which is
        loaded and selected. Since a sub-file is loaded, automatic block
        ([onload] and [onshow]) will be merged. And you need to have the
        sub-file selected in order to use MergeBlock() and MergeField() on it.
        See commands like OPENTBS_SELECT_*. For example, in Ms Word , header and
        footers are loaded, and the main document is loaded and selected, but
        your need to select back a header part in order to use MergeBlock() on
        it.</p>
      <p>Then, it may happens that a TBS tag seems uniformly formatted, while in
        fact the inner XML is split because of small difference in format, small
        different spelling information, or other... In order to avoid inner
        split, you can select the TBS tags, then cut it, and then paste it back
        without formatting. &nbsp;It is “Paste special / Unformatted text” in
        LibreOffice, or “Paste / Keep Text Only” is Ms Office.</p>
      <p> For MS Word, you can also use “OpenTBS plug-in for Microsoft Word”,
        which is given with the standard OpenTBS package. This plug-in gives a
        tag cleaner tool.</p>
      <h3><a id="debug_design"></a>c) The merged document is well opened by its
        application (OpenOffice or Ms Office) but the content is not designed as
        expected</h3>
      <p>First, you can have a look the <a href="#demo">demo templates</a>,
        they contain examples and advices for each type of document.</p>
      <p> And to go further: even if you can edit your template using directly
        OpenOffice or Ms Office, you will probably need to understand the XML
        tags and attributes to complete your merge. The file <a href="xml_synopsis.txt">xml_synopsis.txt</a>
        is a small synopsis of the XML structure you can found in the inner
        source of those documents. Have a look to it if you feel lost.</p>
      <h3><a id="debug_unzip"></a>d) Go deeper in the debugging</h3>
      <p>You can view the inner source of a document using a zip software like <a
          href="http://www.7-zip.org/">7-Zip</a>. It allows you to open an
        archive even if the extension is not ".zip".<br>
      </p>
      <ul>
        <li>Open the merged document with 7-Zip (or your other zip software),</li>
        <li> extract the main XML file (or another file that you've merged),</li>
        <li> then open the XML file in an Text Editor software.</li>
        <li>those XML files are usually saved with no line breaks, which make
          them hard to be read. Some Text Editors can reformat them. You can
          also use the <a href="#debugmode">debug mode</a> to see the formatted
          XML.</li>
        <li>check the structure of the XMK, try some fix and arrangements,
          deleted suspicious parts, ...</li>
        <li>put the modified XML file back to the archive, and test if it's
          correctly opened with its application (OpenOffice, Ms Office)</li>
      </ul>
      <h2><a id="zlib"></a>7. What to do if Zlib extension is not enabled with
        PHP?</h2>
      <p>OpenTBS uses Zlib functions in order to automatically uncompress and
        recompress files stored in the zip archive. If Zlib is not enabled, then
        you have to use your own uncompress/compress tool, or to prepare the
        template to have files uncompressed in the zip archive.</p>
      <p style="text-decoration: underline;">Example to uncompress the
        "content.xml" file in an ODT document using 7-Zip:</p>
      <ol>
        <li>open the ODT file with 7-Zip,</li>
        <li>extract the "content.xml" file from the ODT file in the same folder
          than the ODT file,</li>
        <li>close 7-Zip,</li>
        <li> open 7-Zip, and change current directory to be the same as the ODT
          file</li>
        <li>select the "content.xml" file and click on button [Add], or menu
          [File][7-Zip][Add to archive...],</li>
        <li>a new window named "Add to archive" is opened,
          <ul>
            <li>replace the archive name with the ODT file name,</li>
            <li>set the Compression level to "None",</li>
          </ul>
        </li>
        <li>click on [Ok].</li>
      </ol>
      <p> If you re-open the ODT file with 7-Zip, you can notice that the size
        and the uncompressed size are the same.<br>
        If the file should be placed in a sub-folder of the archive, then open
        the archive and rename the file in order to move it in a folder. For
        example rename "manifest.xml" to "META-INF\manifest.xml" will move it
        into META-INF. But moving the file will no delete the one which has the
        same name in the target folder. You have to go and delete the old one. </p>
      <h2><a id="license"></a>8. License</h2>
      <p>OpenTBS is under <a href="http://www.gnu.org/licenses/lgpl.html">LGPL</a>
        (Lesser General Public License)</p>
      <p>&nbsp;</p>
    </div>
  </body>
</html>
